// api provided by weixin

var Promise = require('promise');
var request = require('request');
// var config = require('../config/config.js')();
var Employee = require('../model/employee.js');
var UrlUtils = require('./UrlUtils.js');
var urlHelper = new UrlUtils();
var debug = require('debug')('weixin');

function WeixinApi() {}
var wp = WeixinApi.prototype;

function _promiseGet(url) {
  return new Promise(function(resolve, reject) {
    request.get(url, function(err, response, body) {
      if (err) throw err;
      resolve(body);
    });
  });
}

/**
 * get access token, use cache
 */
var accessToken = null;
var accessTokenTimeoutAt = 0;
var currPromise = null; // 防止一个时间段内，密集申请token
wp.getAccessToken = function() {
  debug('getAccessToken');
  // check cache
  if (accessToken != null && Date.now() - accessTokenTimeoutAt < 0) {
    // debug('getAccessToken, use cache');
    return Promise.resolve(accessToken);
  }

  // 已经在fetch, 等待即可
  if (currPromise != null) {
    debug('already fetch, waiting return ... ');
    return currPromise;
  }

  // fetch token
  var url = urlHelper.getUrlAccessToken();
  currPromise = _promiseGet(url).then(function(data) {
    // debug('accessToken from weixin ', data);

    var result = JSON.parse(data);
    accessToken = result.access_token;
    if (!accessToken) {
      debug('accessToken fail, result', result);
      return Promise.reject(data);
    }

    debug('accessToken = ', accessToken);
    // cache it
    accessTokenTimeoutAt = Date.now() + result.expires_in * 1000;
    currPromise = null;
    return Promise.resolve(accessToken);
  }, function(err) {
    // debug('error : accessToken from weixin ', err);
    currPromise = null;
    return Promise.reject(err);
  });

  return currPromise;
}


function _promiseFind(mongoModel, findCondition) {
  return new Promise(function(resolve, reject) {
    mongoModel.find(findCondition, function(err, doc) {
      if (err) throw err;
      return resolve(doc);
    });
  });
}

// should we cache it
wp.getUserInfo = function(userid) {
  debug('getUserInfo');
  var self = this;

  return _promiseFind(Employee, {
    weixin_userid: userid
  }).then(function(doc) {
    // debug('find db done,doc=', doc);
    if (doc && doc.length === 1) {
      // debug('getUserInfo, use local mongodb');
      return Promise.resolve(doc[0]);
    } else {
      return self._getUserInfo(userid);
    }
  });
}

wp._getUserInfo = function(userid) {
  return this.getAccessToken().then(function(token) {
    // debug('token getted:', token);
    var url = urlHelper.getUrlUserInfo(userid, token);
    // debug('get userinfo,url=', url);
    return _promiseGet(url);
  }).then(function(data) {
    // debug('userinfo getted:' + data);
    if (!data) {
      return Promise.reject({
        errmsg: 'cannt get info of this user',
        errcode: 400
      });
    }

    var result = JSON.parse(data);
    var employee = new Employee({
      weixin_userid: result.userid,
      name: result.name,
      department: result.department,
      position: result.position,
      mobile: result.mobile,
      email: result.email,
      avatar: result.avatar,
      status: result.status,
      extattr: result.extattr,
    });
    employee.save(function(err) {
      if (err) debug('err: db save err', err);
      // else debug('save userinfo succ');
    });
    return Promise.resolve(employee);
  });
}


wp.getAllUser = function() {
  debug('getAllUser');
  return this.getAccessToken().then(function(token) {
    var url = urlHelper.getUrlAllUser(token);
    return _promiseGet(url);
  });
}


wp.getUrlCode = function() {
  return urlHelper.getUrlCode();
}

wp.getUseridByCode = function(code) {
  debug('getUseridByCode, code=', code);
  return this.getAccessToken().then(function(token) {
    var url = urlHelper.getUrlUserIdByCode(token, code);
    // debug('url=', url);
    return _promiseGet(url);
  }).then(function(data) {
    debug('getUseridByCode,code=' + code);
    debug('data=', data);

    var result = JSON.parse(data);
    var userId = result.UserId;
    if (userId) {
      return Promise.resolve(userId);
    } else {
      return Promise.reject(result);
    }
  });
}

wp.postMsg = function(msgObj) {
  debug("postMsg", JSON.stringify(msgObj));

  return this.getAccessToken().then(function(token) {
    var url = urlHelper.getUrlSendMsg(token);
    return new Promise(function(resolve, reject) {
      request({
        method: 'POST',
        url: url,
        body: JSON.stringify(msgObj)
      }, function(err, response, body) {
        if (err) return reject(err);
        else return resolve(body);
      });
    });

  });
}

module.exports = exports = WeixinApi;
